package com.suray.basic.wcs.plc.pojo.oper.single;

import com.suray.basic.wcs.plc.config.resolver.PlcAnnotation;
import com.suray.basic.wcs.plc.core.PlcOffset;
import com.suray.basic.wcs.plc.enums.Location;
import com.suray.basic.wcs.plc.enums.PlcDeviceType;
import com.suray.basic.wcs.plc.pojo.DeviceBase;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;

import java.io.IOException;

/**
 * 自动升降机
 */
public class AutoHoistOper extends DeviceBase implements DeviceInterface {

    final protected static int OPER_OFF = 0;
    final protected static int OPER_ON = 1;

    /**
     * AB:
     * A（0-9）：无效；1：升降机升；2：升降机降；3：升降机链条机正转；4：升降机链条机反转；5：升降机链条机停止
     * B(0-2):0:无；1输送线进货；2输送线出货
     * **/
    private static final int RISE=10;
    private static final int DROP=20;
    private static final int FORWARD_IN=31;
    private static final int FORWARD_OUT=32;
    private static final int REVERSE_IN=41;
    private static final int REVERSE_OUT=42;

    private static final PlcOffset DEVICE_TYPE = new PlcOffset(0, null);
    private static final PlcOffset IS_OPEN_SHAPE = new PlcOffset(17, 0);
    private static final PlcOffset IS_OPEN_BCR = new PlcOffset(17, 1);
    private static final PlcOffset IS_OPEN_OVERWEIGHT = new PlcOffset(17, 2);

    private static final PlcOffset STOP_STATE = new PlcOffset(18, 0);
    private static final PlcOffset CONTROLLER_MODE_MANUAL = new PlcOffset(18, 1);
    private static final PlcOffset CONTROLLER_MODE_AUTO = new PlcOffset(18, 2);
    private static final PlcOffset MANUAL_UP = new PlcOffset(18, 3);
    private static final PlcOffset MANUAL_DOWN = new PlcOffset(18, 4);
    private static final PlcOffset MANUAL_FORWARD = new PlcOffset(18, 5);
    private static final PlcOffset MANUAL_REVERSE = new PlcOffset(18, 6);
    private static final PlcOffset CLEAR_ERROR_1 = new PlcOffset(18, 7);
    private static final PlcOffset IS_CONTROL = new PlcOffset(18, 8);
    private static final PlcOffset DEVICE_STATE = new PlcOffset(18, 9);
    private static final PlcOffset ELEVATOR_STATE = new PlcOffset(18, 10);
    private static final PlcOffset CONVEYOR_STATE = new PlcOffset(18, 11);
    private static final PlcOffset ERROR_STATE = new PlcOffset(18, 12);
    private static final PlcOffset RISE_LIMIT = new PlcOffset(18, 13);
    private static final PlcOffset DROP_LIMIT = new PlcOffset(18, 14);
    private static final PlcOffset RISE_IN_PLACE = new PlcOffset(18, 15);

    private static final PlcOffset DROP_IN_PLACE = new PlcOffset(19, 0);
    private static final PlcOffset LIMIT_1 = new PlcOffset(19, 1);
    private static final PlcOffset LIMIT_3 = new PlcOffset(19, 2);
    private static final PlcOffset IN_PLACE_SIGNAL_1 = new PlcOffset(19, 3);
    private static final PlcOffset IN_PLACE_SIGNAL_2 = new PlcOffset(19, 4);
    private static final PlcOffset ERROR_INFO = new PlcOffset(20, null);
    private static final PlcOffset CHECK_NO = new PlcOffset(21, null);
    private static final PlcOffset CURRENT_DEVICE_TYPE = new PlcOffset(22, null);
    //设备类型 写
    private static final int DEVICETYPE = 0;
    //位移量 写
    private static final int MOVEMENT = 1;
    //升降自动速度 写
    private static final int LIFT_AUTO_SPEED = 2;
    //升降自动加速时间 写
    private static final int LIFT_AUTO_ACC = 3;
    //升降自动减速时间 写
    private static final int LIFT_AUTO_DEC = 4;
    //升降手动速度 写
    private static final int LIFT_MANUAL_SPEED = 5;
    //升降手动加速时间 写
    private static final int LIFT_MANUAL_ACC = 6;
    //升降手动减速时间 写
    private static final int LIFT_MANUAL_DEC = 7;
    //输送线自动速度 写
    private static final int CONVEYOR_AUTO_SPEED = 8;
    //输送线自动加速时间 写
    private static final int CONVEYOR_AUTO_ACC = 9;
    //输送线自动减速时间 写
    private static final int CONVEYOR_AUTO_DEC = 10;
    //输送线手动速度 写
    private static final int CONVEYOR_MANUAL_SPEED = 11;
    //输送线手动加速时间 写
    private static final int CONVEYOR_MANUAL_ACC = 12;
    //输送线手动减速时间
    private static final int CONVEYOR_MANUAL_DEC = 13;
    //升降机运行 写
    private static final int TASK_ACTION = 16;
    //故障清除 写
    private static final int CLEAR_ERROR = 17;

    /**
     * 设备类型
     */
    private Integer deviceType;
    /**
     * 设备位移量
     */
    private Integer movement;
    /**
     * 升降自动速度
     */
    private Integer liftAutoSpeed;
    /**
     * 升降自动加速
     */
    private Integer liftAutoAcc;
    /**
     * 升降自动减速
     */
    private Integer liftAutoDec;
    /**
     * 升降手动速度
     */
    private Integer liftManualSpeed;
    /**
     * 升降手动加速
     */
    private Integer liftManualAcc;
    /**
     * 升降手动减速
     */
    private Integer liftManualDec;
    /**
     * 输送线自动速度
     */
    private Integer conveyorAutoSpeed;
    /**
     * 输送线自动加速
     */
    private Integer conveyorAutoAcc;
    /**
     * 输送线自动减速
     */
    private Integer conveyorAutoDec;
    /**
     * 输送线手动速度
     */
    private Integer conveyorManualSpeed;
    /**
     * 输送线手动加速
     */
    private Integer conveyorManualAcc;
    /**
     * 输送线手动减速
     */
    private Integer conveyorManualDec;
    /**
     * 自动升降机运行
     */
    private Integer taskAction;
    /**
     * 故障清除
     */
    private boolean clearError;
    /**
     * 外形检测开启与否
     */
    private boolean isOpenShape;
    /**
     * 扫码故障灯是否开启
     */
    private boolean isOpenBcr;
    /**
     * 超重灯是否开启
     */
    private boolean isOpenOverweight;
    /**
     * 系统急停
     */
    private boolean stopState;
    /**
     * 系统手动/本地模式
     */
    private boolean controllerMode;
    /**
     * 手动上升
     */
    private boolean manualUp;
    /**
     * 手动下降
     */
    private boolean manualDown;
    /**
     * 手动输送线正转
     */
    private boolean manualForward;
    /**
     * 手动输送线反转
     */
    private boolean manualReverse;
    /**
     * 故障复位
     */
    private boolean clearError1;
    /**
     * WCS是否可控
     */
    private boolean isControl;
    /**
     * 设备正在运行中
     */
    private boolean deviceState;
    /**
     * 升降正在运行
     */
    private boolean elevatorState;
    /**
     * 输送线正在运行
     */
    private boolean conveyorState;
    /**
     * 故障报警状态
     */
    private boolean errorState;
    /**
     * 上升极限
     */
    private boolean riseLimit;
    /**
     * 下降极限
     */
    private boolean dropLimit;
    /**
     * 上升到位
     */
    private boolean riseInPlace;
    /**
     * 下降到位
     */
    private boolean dropInPlace;
    /**
     * 输送线1方向限位
     */
    private boolean limit1;
    /**
     * 输送线3方向限位
     */
    private boolean limit3;
    /**
     * 输送线1到位
     */
    private boolean inPlaceSignal1;
    /**
     * 输送线2到位
     */
    private boolean inPlaceSignal2;
    /**
     * 故障码
     */
    private Integer errorInfo;
    /**
     * 校准位
     */
    private Integer checkNo;
    /**
     * 当前设备类型
     */
    private Integer currentDeviceType;


    public AutoHoistOper(PlcDeviceType plcDeviceType, int startNo, String deviceName, int deviceNo, Coord coord,
                         Location location, Coord lockLocation, long deviceId, Integer gridzMax, Integer gridzRelative,
                         int plcId) {
        super(plcDeviceType, startNo, deviceName, deviceNo, coord, location, lockLocation, deviceId, gridzMax,
                gridzRelative, plcId);
    }

    @PlcAnnotation(value = "设置设备类型")
    public void setDeviceType()throws IOException {
        oper("设置设备类型", this.getClass(), DEVICETYPE,3,8);
    }

    public Integer getDeviceType() {
        return readPlc(DEVICE_TYPE);
    }

    public Integer getMovement() {
        return readPlc(new PlcOffset(MOVEMENT, null));
    }

    /**
     * 平台升位移量
     *
     * @return
     */
    @PlcAnnotation(value = "平台升位移量")
    public void setPlatformRiseMovement() throws IOException {
        oper("平台升位移量", this.getClass(), MOVEMENT, 10, 11);
    }

    /**
     * 平台降位移量
     *
     * @return
     */
    @PlcAnnotation(value = "平台降位移量")
    public void setPlatformDropMovement() throws IOException {
        oper("平台降位移量", this.getClass(), MOVEMENT, 10, 12);
    }

    public Integer getLiftAutoSpeed() {
        return readPlc(new PlcOffset(LIFT_AUTO_SPEED, null));
    }

    /**
     * 设置升降自动速度
     *
     * @return
     */
    @PlcAnnotation(value = "设置升降自动速度")
    public void setLiftAutoSpeed(int speed) throws IOException {
//        int[] sd = {OPER_ON, speed};
        LoggerUtil.info("升降自动速度:" + speed, this.getClass());
        oper("设置升降自动速度", this.getClass(), LIFT_AUTO_SPEED, 10, speed);
    }

    public Integer getLiftAutoAcc() {
        return readPlc(new PlcOffset(LIFT_AUTO_ACC, null));
    }

    /**
     * 设置升降自动加速时间
     *
     * @return
     */
    @PlcAnnotation(value = "设置升降自动加速时间")
    public void setLiftAutoAcc(int time) throws IOException {
//        int[] tm = {OPER_ON, time};
        LoggerUtil.info("升降自动加速时间:" + time, this.getClass());
        oper("设置升降自动加速时间", this.getClass(), LIFT_AUTO_ACC, 10, time);
    }

    public Integer getLiftAutoDec() {
        return readPlc(new PlcOffset(LIFT_AUTO_DEC, null));
    }

    /**
     * 设置升降自动减速时间
     *
     * @return
     */
    @PlcAnnotation(value = "设置升降自动减速时间")
    public void setLiftAutoDec(int time) throws IOException {
        LoggerUtil.info("升降自动减速时间:" + time, this.getClass());
        oper("设置升降自动减速时间", this.getClass(), LIFT_AUTO_DEC, 10, time);
    }

    public Integer getLiftManualSpeed() {
        return readPlc(new PlcOffset(LIFT_MANUAL_SPEED, null));
    }

    /**
     * 设置升降手动速度
     *
     * @return
     */
    @PlcAnnotation(value = "设置升降手动速度")
    public void setLiftManualSpeed(int speed) throws IOException {
        LoggerUtil.info("升降手动速度:" + speed, this.getClass());
        oper("设置升降手动速度", this.getClass(), LIFT_MANUAL_SPEED, 10, speed);
    }

    public Integer getLiftManualAcc() {
        return readPlc(new PlcOffset(LIFT_MANUAL_ACC, null));
    }

    /**
     * 设置升降手动加速时间
     *
     * @return
     */
    @PlcAnnotation(value = "设置升降手动加速时间")
    public void setLiftManualAcc(int time) throws IOException {
        LoggerUtil.info("升降手动加速时间:" + time, this.getClass());
        oper("设置升降手动加速时间", this.getClass(), LIFT_MANUAL_ACC, 10, time);
    }

    public Integer getLiftManualDec() {
        return readPlc(new PlcOffset(LIFT_MANUAL_DEC, null));
    }

    /**
     * 设置升降手动减速时间
     *
     * @return
     */
    @PlcAnnotation(value = "设置升降手动减速时间")
    public void setLiftManualDec(int time) throws IOException {
        LoggerUtil.info("升降手动减速时间:" + time, this.getClass());
        oper("设置升降手动减速时间", this.getClass(), LIFT_MANUAL_DEC, 10, time);
    }

    public Integer getConveyorAutoSpeed() {
        return readPlc(new PlcOffset(CONVEYOR_AUTO_SPEED, null));
    }

    /**
     * 设置输送线自动速度
     *
     * @return
     */
    @PlcAnnotation(value = "设置输送线自动速度")
    public void setConveyorAutoSpeed(int speed) throws IOException {
        LoggerUtil.info("输送线自动速度:" + speed, this.getClass());
        oper("设置输送线自动速度", this.getClass(), CONVEYOR_AUTO_SPEED, 10, speed);
    }

    public Integer getConveyorAutoAcc() {
        return readPlc(new PlcOffset(CONVEYOR_AUTO_ACC, null));
    }

    /**
     * 设置输送线自动加速时间
     *
     * @return
     */
    @PlcAnnotation(value = "设置输送线自动加速时间")
    public void setConveyorAutoAcc(int time) throws IOException {
        LoggerUtil.info("输送线自动加速时间:" + time, this.getClass());
        oper("设置输送线自动加速时间", this.getClass(), CONVEYOR_AUTO_ACC, 10, time);
    }

    public Integer getConveyorAutoDec() {
        return readPlc(new PlcOffset(CONVEYOR_AUTO_DEC, null));
    }

    /**
     * 设置输送线自动减速时间
     *
     * @param time
     * @throws IOException
     */
    @PlcAnnotation(value = "设置输送线自动减速时间")
    public void setConveyorAutoDec(int time) throws IOException {
        LoggerUtil.info("输送线自动减速时间:" + time, this.getClass());
        oper("设置输送线自动减速时间", this.getClass(), CONVEYOR_AUTO_DEC, 10, time);
    }

    public Integer getConveyorManualSpeed() {
        return readPlc(new PlcOffset(CONVEYOR_MANUAL_SPEED, null));
    }

    /**
     * 设置输送线手动速度
     *
     * @return
     */
    @PlcAnnotation(value = "设置输送线手动速度")
    public void setConveyorManualSpeed(int speed) throws IOException {
        LoggerUtil.info("输送线手动速度:" + speed, this.getClass());
        oper("设置输送线手动速度", this.getClass(), CONVEYOR_MANUAL_SPEED, 10, speed);
    }

    public Integer getConveyorManualAcc() {
        return readPlc(new PlcOffset(CONVEYOR_MANUAL_ACC, null));
    }

    /**
     * 设置输送线手动加速时间
     *
     * @param time
     * @throws IOException
     */
    @PlcAnnotation(value = "设置输送线手动加速时间")
    public void setConveyorManualAcc(int time) throws IOException {
        LoggerUtil.info("输送线手动加速时间:" + time, this.getClass());
        oper("设置输送线手动加速时间", this.getClass(), CONVEYOR_MANUAL_ACC, 10, time);
    }

    public Integer getConveyorManualDec() {
        return readPlc(new PlcOffset(CONVEYOR_MANUAL_DEC, null));
    }

    /**
     * 设置输送线手动减速时间
     *
     * @param time
     * @throws IOException
     */
    @PlcAnnotation(value = "设置输送线手动减速时间")
    public void setConveyorManualDec(int time) throws IOException {
        LoggerUtil.info("输送线手动减速时间:" + time, this.getClass());
        oper("设置输送线手动减速时间", this.getClass(), CONVEYOR_MANUAL_DEC, 10, time);
    }

    public Integer getTaskAction() {
        return readPlc(new PlcOffset(TASK_ACTION, null));
    }
    /**
     * 平台上升
     *
     * @throws IOException
     */
    @PlcAnnotation(value = "平台上升")
    public void platformRise() throws IOException {
        oper("平台上升", this.getClass(), TASK_ACTION, 10, RISE);
    }
    /**
     * 平台下降
     *
     * @throws IOException
     */
    @PlcAnnotation(value = "平台下降")
    public void platformDrop() throws IOException {
        oper("平台下降", this.getClass(), TASK_ACTION, 10, DROP);
    }
    /**
     * 正转入库
     *
     * @throws IOException
     */
    @PlcAnnotation(value = "正转入库")
    public void platformForwardIn() throws IOException {
        oper("正转入库", this.getClass(), TASK_ACTION, 10, FORWARD_IN);
    }

    /**
     * 正转出库
     *
     * @throws IOException
     */
    @PlcAnnotation(value = "正转出库")
    public void platformForwardOut() throws IOException {
        oper("正转出库", this.getClass(), TASK_ACTION, 10, FORWARD_OUT);
    }

    /**
     * 反转入库
     *
     * @throws IOException
     */
    @PlcAnnotation(value = "反转入库")
    public void platformReverseIn() throws IOException {
        oper("反转入库", this.getClass(), TASK_ACTION, 10, REVERSE_IN);
    }

    /**
     * 反转出库
     *
     * @throws IOException
     */
    @PlcAnnotation(value = "反转出库")
    public void platformReverseOut() throws IOException {
        oper("反转出库", this.getClass(), TASK_ACTION, 10, REVERSE_OUT);
    }

    public boolean isClearError() {
        return readPlc(new PlcOffset(CLEAR_ERROR, 8)) == 1;
    }

    /**
     * 故障清除
     *
     * @return
     */
    @PlcAnnotation(value = "自动升降机故障清除")
    public void setClearError() throws IOException {
        oper("自动升降机故障清除", this.getClass(), CLEAR_ERROR, 10, OPER_ON);
    }

    public boolean isOpenShape() {
        return readPlc(IS_OPEN_SHAPE) == 1;
    }

    public boolean isOpenBcr() {
        return readPlc(IS_OPEN_BCR) == 1;
    }

    public boolean isOpenOverweight() {
        return readPlc(IS_OPEN_OVERWEIGHT) == 1;
    }

    public boolean isStopState() {
        return readPlc(STOP_STATE) == 1;
    }

    public boolean isControllerModeManual() {
        return readPlc(CONTROLLER_MODE_MANUAL) == 1;
    }
    public boolean isControllerModeAuto() {
        return readPlc(CONTROLLER_MODE_AUTO) == 1;
    }
    public boolean isManualUp() {
        return readPlc(MANUAL_UP) == 1;
    }

    public boolean isManualDown() {
        return readPlc(MANUAL_DOWN) == 1;
    }

    public boolean isManualForward() {
        return readPlc(MANUAL_FORWARD) == 1;
    }

    public boolean isManualReverse() {
        return readPlc(MANUAL_REVERSE) == 1;
    }

    public boolean isClearError1() {
        return readPlc(CLEAR_ERROR_1) == 1;
    }

    public boolean isControl() {
        return readPlc(IS_CONTROL) == 1;
    }

    public boolean isDeviceState() {
        return readPlc(DEVICE_STATE) == 1;
    }

    public boolean isElevatorState() {
        return readPlc(ELEVATOR_STATE) == 1;
    }

    public boolean isConveyorState() {
        return readPlc(CONVEYOR_STATE) == 1;
    }

    public boolean isErrorState() {
        return readPlc(ERROR_STATE) == 1;
    }

    public boolean isRiseLimit() {
        return readPlc(RISE_LIMIT) == 1;
    }

    public boolean isDropLimit() {
        return readPlc(DROP_LIMIT) == 1;
    }

    public boolean isRiseInPlace() {
        return readPlc(RISE_IN_PLACE) == 1;
    }

    public boolean isDropInPlace() {
        return readPlc(DROP_IN_PLACE) == 1;
    }

    public boolean isLimit1() {
        return readPlc(LIMIT_1) == 1;
    }

    public boolean isLimit3() {
        return readPlc(LIMIT_3) == 1;
    }

    public boolean isInPlaceSignal1() {
        return readPlc(IN_PLACE_SIGNAL_1) == 1;
    }

    public boolean isInPlaceSignal2() {
        return readPlc(IN_PLACE_SIGNAL_2) == 1;
    }

    public Integer getErrorInfo() {
        return readPlc(ERROR_INFO);
    }

    public Integer getCheckNo() {
        return readPlc(CHECK_NO);
    }

    public Integer getCurrentDeviceType() {
        return readPlc(CURRENT_DEVICE_TYPE);
    }

    public boolean hasCargo() {
        return isInPlaceSignal1() || isInPlaceSignal2();
    }

    @Override
    public boolean inCargoSignal() {
        return isInPlaceSignal1();
    }

    @Override
    public boolean outCargoSignal() {
        return isInPlaceSignal2();
    }

    @Override
    public boolean permitRun() {
        return isControl() && !isRunning();
    }

    @Override
    public boolean canControl() {
        return isControl();
    }

    @Override
    public boolean isRunning() {
        return isDeviceState();
    }

    @Override
    public boolean isError() {
        return getErrorInfo() > 0;
    }

    @Override
    public Integer errorCode() {
        return getErrorInfo();
    }

    @Override
    public Integer getTaskNo() {
        throw new RuntimeException("不支持的方法");
    }

    @Override
    public Integer getTaskStartLocation() {
        throw new RuntimeException("不支持的方法");
    }

    @Override
    public Integer getTaskEndLocation() {
        throw new RuntimeException("不支持的方法");
    }

    @Override
    public void sendConveryTask(int taskNo, int startDeviceNo, int endDeviceNo) throws IOException {
        throw new RuntimeException("不支持的方法");
    }

    @Override
    public void clearTaskNo() throws IOException {
        throw new RuntimeException("不支持的方法");
    }
}
